#include "dominion.h"
#include <stdio.h>
#include "rngs.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include "interface.h"
#include <string.h>

#define SPEC 0
#define TEST 1

int generateFavoriteKingdomCard(int kingdomCards[]){
	int min = 0;
	int max = 9;
	double scaled = (double)rand()/RAND_MAX;
	int i = (max - min +1)*scaled + min;
	return kingdomCards[i];
}

int getRandomNumOfPlayers(){
	int min = 2;
	int max = 4;
	double scaled = (double)rand()/RAND_MAX;
	return (max - min +1)*scaled + min;
}

int getRandomKingdomCard(){
	int min = 7;
	int max = 26;
	double scaled = (double)rand()/RAND_MAX;
	return (max - min +1)*scaled + min;
}

int hasKingdomCard(int array[], int card){
	for(int i = 0; i < 10; i++){
		if (array[i] == card){
				return 1;
		}
	}
	return 0;
}

void pickRandomKingdomCards(int nums[]){
	for(int i = 0; i < 10; i++){
		int randCard = getRandomKingdomCard();
		while(1){	
			if (hasKingdomCard(nums, randCard) || randCard == 20 || randCard == 18 || randCard == 9 || randCard == 11 || randCard == 12
				|| randCard == 15 || randCard == 17 || randCard == 21 || randCard == 24){
				randCard = getRandomKingdomCard();
				continue;
			}
			break;
   		}
		nums[i] = randCard;
	}
}

void printArray(int nums[], int length){
	for(int i = 0; i < length; i++){
		printf("%d", nums[i]);
		if( i < length - 1){
			printf(",");
		}else{
			printf("\n");
		}
	}
}

void getMoneyCount(struct gameState *G, int *money){
  for (int i = 0; i < numHandCards(G); i++) {
    if (handCard(i, G) == copper){
    	money += 1;
    }
	  else if (handCard(i, G) == silver){
	  	money += 2;
	  }
	  else if (handCard(i, G) == gold){
	   	money += 3;
	  }
	}
}

void getFavKingdomIndex(int currentPlayer, struct gameState *G, int playerFavorites[], int *favoriteKingdomIndex){
	int favorite = playerFavorites[currentPlayer];
	for (int i = 0; i < numHandCards(G); i++) {
	  if (handCard(i, G) == favorite){
	   	*favoriteKingdomIndex = i;
	  }
	}
}

int getActionCardIndex(int currentPlayer, struct gameState *G){
	for (int i = 0; i < numHandCards(G); i++) {
	  if (handCard(i, G) > 7){
	   	return i;
	  }
	}
	return -1;
}

int playMoneyCards(struct gameState *G){
	int money = 0;
	for(int i = 0; i < numHandCards(G); i++){
		if (handCard(i, G) == copper){
			playCard(i, -1, -1, -1, G);
			if(SPEC == 1){
			  printf("Player %d played copper.\n", whoseTurn(G));
		  }
			money++;
		}
		else if (handCard(i, G) == silver){
			playCard(i, -1, -1, -1, G);
			if(SPEC == 1){
				printf("Player %d played silver.\n", whoseTurn(G));
			}
			money += 2;
		}
		else if (handCard(i, G) == gold){
			playCard(i, -1, -1, -1, G);
			if(SPEC == 1){
				printf("Player %d played gold.\n`", whoseTurn(G));
			}
			money += 3;
		}
	}
	return money;
}

void tryToBuyCards(int favoriteKingdomCard, struct gameState *G, int *money,int *numOfFavKingdomCards){
	int favCardCost = getCost(favoriteKingdomCard);
  if (*money >= 8) {
  	if(SPEC == 1){
    	printf("0: bought province\n");
    }
    buyCard(province, G);
  }
  else if (*money >= 6) {
  	if(SPEC == 1){
    	printf("0: bought gold\n"); 
    }
    buyCard(gold, G);
  }
  else if ((*money >= favCardCost)) {
  	if(SPEC == 1){
    	printf("0: bought kingdom #%d\n", favoriteKingdomCard);
  	}	
    buyCard(favoriteKingdomCard, G);
    *numOfFavKingdomCards++;
  }
  else if (*money >= 3) {
  	if(SPEC == 1){
    	printf("0: bought silver\n");
    }
    buyCard(silver, G);
  }
}

void myPrintScores(int numPlayers, struct gameState *G){
	for(int p = 0; p < numPlayers; p++){
		printf ("Player %d scored: %d\n", p, scoreFor(p, G));
	}
}

void printWinners(int players[MAX_PLAYERS]){
	for(int i = 0; i < MAX_PLAYERS; i++){
		if (players[i] == 1){
			printf("Player %d won the game.\n", i);
		}
	}
}

void myCardNumToName(int card, char *name){
	switch(card){
  case curse: strcpy(name,"Curse");
    break;
  case estate: strcpy(name,"Estate");
    break;
  case duchy: strcpy(name,"Duchy");
    break;
  case province: strcpy(name,"Province");
    break;
  case copper: strcpy(name,"Copper");
    break;
  case silver: strcpy(name,"Silver");
    break;
  case gold: strcpy(name,"Gold");
    break;
  case adventurer: strcpy(name,"Adventurer");
    break;
  case council_room: strcpy(name,"Council Room");
    break;
  case feast: strcpy(name,"Feast");
    break;
  case gardens: strcpy(name,"Gardens");
    break;
  case mine: strcpy(name,"Mine");
    break;
  case remodel: strcpy(name,"Remodel");
    break;
  case smithy: strcpy(name,"Smithy");
    break;
  case village: strcpy(name,"Village");
    break;
  case baron: strcpy(name,"Baron");
    break;
  case great_hall: strcpy(name,"Great Hall");
    break;
  case minion: strcpy(name,"Minion");
    break;
  case steward: strcpy(name,"Steward");
    break;
  case tribute: strcpy(name,"Tribute");
    break;
  case ambassador: strcpy(name,"Ambassador");
    break;
  case cutpurse: strcpy(name,"Cutpurse");
    break;
  case embargo: strcpy(name,"Embargo");
    break;
  case outpost: strcpy(name,"Outpost");
    break;
  case salvager: strcpy(name,"Salvager");
    break;
  case sea_hag: strcpy(name,"Sea Hag");
    break;
  case treasure_map: strcpy(name,"Treasure Map");
    break;

  default: strcpy(name,"?");
  }
}

void revealHand(int player, struct gameState *G){
	printf("Player %d is holding cards: ", player);
	char name[MAX_STRING_LENGTH];
	for (int k = 0; k < G->handCount[player]; k++){
			int cardNum = G->hand[player][k];
			myCardNumToName(cardNum, name);
			printf("%s ", name);
	}
	printf("\n");
}

void testPlayCard(int card, int returnVal, int *errorCount){
	char * fail;
	if(returnVal != 0){
		fail = "FAIL\0";
		(*errorCount)++;
	}else{
		fail = "PASS\0";
	}
	printf("playCard(%2d) returns: %2d \t%s\n", card, returnVal, fail);
}


int runGame(int *errorCount)
{
	// timing
	clock_t timeBefore = clock();
	clock_t totalExecTime;

  // random seed
  srand(time(NULL));
	// globals
	struct gameState G;
	int money = 0;
	int numOfFavKingdomCards = 0;
  int favoriteKingdomIndex = -1;
  int randomActionCardIndex = -1;

  /*************** RANDOMIZE ALL ***************/
  // Pick a random number of players in range 2, 4 inclusive
  int numPlayers = getRandomNumOfPlayers();
  if(SPEC == 1){
  	printf("Number of players: %d\n", numPlayers);
  }
    
  // Pick 10 random, unique kingdom car
  int kingdomCards[10];
  pickRandomKingdomCards(kingdomCards);
  if(SPEC == 1){
  	printf("Kingdom cards: ");
  	printArray(kingdomCards, 10);
	}

  // Pick a random seed for init
  int randSeed = rand();
  if(SPEC == 1){
  	printf("Random seed for initializeGame: %d\n", randSeed);
	}

  // Assign favorite kingdom cards
  int playerFavorites[numPlayers];
  for(int p = 0; p < numPlayers; p++){
  	playerFavorites[p] = generateFavoriteKingdomCard(kingdomCards);
  	if(SPEC == 1){
  		printf("Player %d's favorite kingdom card: %d\n", p, playerFavorites[p]);
  	}
  }

  // Initalize game
  if(SPEC == 1){
  	printf("Starting game...\n");
  }
  initializeGame(numPlayers, kingdomCards, randSeed, &G);



	while(!isGameOver(&G)){
		money = 0;
		getMoneyCount(&G, &money);

		favoriteKingdomIndex = -1;

		switch(0){
			case 0:
				if(SPEC == 1){
					revealHand(whoseTurn(&G), &G);
				}
				getFavKingdomIndex(whoseTurn(&G), &G, playerFavorites, &favoriteKingdomIndex);
				if (favoriteKingdomIndex != -1){
					int favoriteKingdomCard = playerFavorites[whoseTurn(&G)];
					int choice1 = 1;
					int choice2 = 2;
					int choice3 = 3;
					int retVal = playCard(favoriteKingdomIndex, choice1, choice2, choice3, &G);
					if(TEST == 1){
						testPlayCard(G.hand[whoseTurn(&G)][favoriteKingdomIndex], retVal, errorCount);
					}
					if(SPEC == 1){
						printf("Player %d, played kingdom card #2%d from position %d.\n", 
							whoseTurn(&G),
							playerFavorites[whoseTurn(&G)],
							favoriteKingdomIndex);
					}
					money = playMoneyCards(&G);
					tryToBuyCards(playerFavorites[whoseTurn(&G)], &G, &money, &numOfFavKingdomCards);
					if(SPEC == 1){	
						printf("Player %d: end turn\n", whoseTurn(&G));
		      }
		      endTurn(&G);
				}else{
					// get random action card
					randomActionCardIndex = getActionCardIndex(whoseTurn(&G), &G);
					if(randomActionCardIndex != -1){
						int retVal = playCard(randomActionCardIndex, 1, 1, 1, &G);
						if(TEST == 1){
							testPlayCard(G.hand[whoseTurn(&G)][randomActionCardIndex], retVal, errorCount);
						}
						if(SPEC == 1){
						printf("Player %d, played card #%d from position %d.\n", 
							whoseTurn(&G),
							handCard(randomActionCardIndex, &G),
							randomActionCardIndex);
						}
					}
					money = playMoneyCards(&G);
					if(SPEC == 1){
						printf("Player %d has %d money.\n", whoseTurn(&G), money);
					}
					tryToBuyCards(playerFavorites[whoseTurn(&G)], &G, &money, &numOfFavKingdomCards);
					if(SPEC == 1){
						printf("Player %d: end turn\n", whoseTurn(&G));
					}
					endTurn(&G);
				}
				break;
			case 1:
				break;
				
			case 2:
				break;
			
			case 3:
				break;
			
		}
	clock_t timeAfter = clock();
	totalExecTime = timeAfter - timeBefore;

	}

	printf("total time: %f\n", (double)totalExecTime);

	if(SPEC == 1){
		int players[MAX_PLAYERS];
		getWinners(players, &G);
		printWinners(players);
		myPrintScores(numPlayers, &G);
	}
  return 0;
}

int main(int argc, char const *argv[])
{
	int errorCount = 0;
	int gameCount = 0;
	int maxGames = (int) strtol(argv[1], (char **)NULL, 10);
	while(gameCount < maxGames){
		printf("Game number %d.\n", gameCount);
		runGame(&errorCount);
		gameCount++;
	}
	printf("%d total errors after running %d games\n", errorCount, gameCount);
	return 0;
}
